-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Increase static typing strictness #10530
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
cc: @danieleades A |
danieleades
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's a few blanket warnings suppressions that can be tightened, although these are technically adjacent to the changed code
| supported_data_uri_images = False | ||
|
|
||
| def __init__(self, app: "Sphinx") -> None: | ||
| def __init__(self, app: "Sphinx", env: BuildEnvironment = None) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| def __init__(self, app: "Sphinx", env: BuildEnvironment = None) -> None: | |
| def __init__(self, app: "Sphinx", env: Optional[BuildEnvironment] = None) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here I'm using None as a sentinel, I could have equally used .... I don't want to indicate to users that None is a valid type, which I believe using Optional[] syntax would do. Hence I'm -1 on both these suggestions, unless you've alternate ideas?
A
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's not how this works. Setting a default value of None effectively coerces the type from Type to Optional[Type]. That is, the former desugars to the latter implicitly. The setting that controls this is called no-implicit-optional.
It's better to be explicit and use the Optional. If using 'strict' mypy checking, failing to use it becomes a hard error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added no_implicit_optional = True and everything still passes -- is this what you meant?
A
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, it should be an error with that config. Not sure why you're not seeing one, could be you're hitting the maximum number of errors, or it could be a false negative. In either case you should be able to convince yourself from the documentation that using the explicit Optional is strictly correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah i think i see the issue. you have this-
strict_optional = False
no_implicit_optional = Trueto see these errors your would need
strict_optional = True
no_implicit_optional = Trueif you really want to give yourself nightmares, try
strict = True|
|
||
| def __init__(self, app: Sphinx) -> None: | ||
| super().__init__(app) | ||
| def __init__(self, app: Sphinx, env: BuildEnvironment = None) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| def __init__(self, app: Sphinx, env: BuildEnvironment = None) -> None: | |
| def __init__(self, app: Sphinx, env: Optional[BuildEnvironment] = None) -> None: |
sphinx/registry.py
Outdated
| f"'env'argument. Report this bug to the developers of your custom builder, " | ||
| f"this is likely not a issue with Sphinx. The 'env' argument will be required " | ||
| f"from Sphinx 7.", RemovedInSphinx70Warning, stacklevel=2) | ||
| return self.builders[name](app) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The new code never calls
set_environment(). As a result, custom builders will get crashed because the env object is None. - This will also cause another warning on
Builder.__init__(). The users will see warnings twice or more.
Please be careful to changing the API. I believe Sphinx is not only an application but also a framework. So I consider this is a mix of refactoring and API changing. Is it intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was concerned the potential to call set_environment twice, but it seems that wouldn't be a problem, so updated. I also added a check so that we only issue one warning.
Please be careful to changing the API. I believe Sphinx is not only an application but also a framework. So I consider this is a mix of refactoring and API changing. Is it intended?
This PR shouldn't have any end-user facing changes. I would say I consider Sphinx more of an application with a plugin mechanism though, rather than a library/framework -- we should be able to make changes that improve things on our end, although of course seeking to keep backwards compatability.
A
|
@AA-Turner this is already a herculean effort, nice work! If you're not able to squash all of the errors in this PR, you may want to consider whitelisting a subset of files with that would look something like current: [mypy]
python_version = 3.6
disallow_incomplete_defs = True
show_column_numbers = True
show_error_context = True
ignore_missing_imports = True
follow_imports = skip
check_untyped_defs = True
warn_unused_ignores = True
strict_optional = Falsenew: [mypy]
python_version = 3.6
disallow_incomplete_defs = True
show_column_numbers = True
show_error_context = True
ignore_missing_imports = True
follow_imports = skip
check_untyped_defs = True
warn_unused_ignores = True
[mypy-some.module]
strict_optional = False
[mypy-some.other.module]
strict_optional = False(i think? i usually use |
|
I'm not going to do the whitelist approach -- I got to 34 modules and the list is ridiculous (100+ lines long) and there are still 244 errors reported. My progress is in the details block for posterity, but I don't reccomend adding it to Detailsstrict_optional = True
no_implicit_optional = True
[mypy-sphinx.application]
strict_optional = False
[mypy-sphinx.writers.latex]
strict_optional = False
[mypy-sphinx.builders.latex]
strict_optional = False
[mypy-sphinx.builders.html]
strict_optional = False
[mypy-sphinx.builders.gettext]
strict_optional = False
[mypy-sphinx.builders.singlehtml]
strict_optional = False
[mypy-sphinx.builders.dirhtml]
strict_optional = False
[mypy-sphinx.builders.latex.transforms]
strict_optional = False
[mypy-sphinx.domains.c]
strict_optional = False
[mypy-sphinx.domains.cpp]
strict_optional = False
[mypy-sphinx.domains.javascript]
strict_optional = False
[mypy-sphinx.domains.python]
strict_optional = False
[mypy-sphinx.domains.changeset]
strict_optional = False
[mypy-sphinx.builders.xml]
strict_optional = False
[mypy-sphinx.builders.manpage]
strict_optional = False
[mypy-sphinx.builders.texinfo]
strict_optional = False
[mypy-sphinx.writers.texinfo]
strict_optional = False
[mypy-sphinx.writers.text]
strict_optional = False
[mypy-sphinx.writers.html5]
strict_optional = False
[mypy-sphinx.writers.html]
strict_optional = False
[mypy-sphinx.environment]
strict_optional = False
[mypy-sphinx.environment.adapters.indexentries]
strict_optional = False
[mypy-sphinx.util.docfields]
strict_optional = False
[mypy-sphinx.directives.code]
strict_optional = False
[mypy-sphinx.transforms.post_transforms.images]
strict_optional = False
[mypy-sphinx.builders.linkcheck]
strict_optional = False
[mypy-sphinx.ext.autosummary]
strict_optional = False
[mypy-sphinx.ext.autodoc]
strict_optional = False
[mypy-sphinx.ext.apidoc]
strict_optional = False
[mypy-sphinx.ext.autosummary.generate]
strict_optional = False
[mypy-sphinx.ext.imgmath]
strict_optional = False
[mypy-sphinx.ext.intersphinx]
strict_optional = False
[mypy-sphinx.ext.mathjax]
strict_optional = False
[mypy-sphinx.ext.graphviz]
strict_optional = False
[mypy-sphinx.ext.inheritance_diagram]
strict_optional = FalseA |
|
Followup:
This PR was never about getting all of them, it started as ensuring MyPy passes on Windows and then I fixed some "easy" targets. C.f. Zen, pragmatism & purity...! A |
Goes from 916 to 650 errors with
strict_optional = True.Feature or Bugfix
xref: #10528
A